<?php
include "wx.config.php";

define("RouterApi", serialize($RouterApi));

$wechat = new wx_sample();
$wechat->init();

class wx_sample{
  	private $RouterApi;
    // 构造函数
  	public function __construct() {
    	$this->RouterApi = unserialize(RouterApi);
  	}
    public function init(){
        // 检测入口参数
        $queryString = $this->queryFormat();

        // 读取cookie中的openid
        $resultData = $this->authcode($_COOKIE['resultData'],'DECODE');

        $this->wxlog($resultData,__FILE__,__LINE__,'cookie值');

        // 读取不到openid 去微信授权获取
        if($resultData == '') {

            // 获取配置
            $appid = $this->RouterApi['appid'];
            $redirect_uri = urlencode($this->RouterApi['redirect_uri']);


            //拼接授权地址
            $authorUrl = "location: https://open.weixin.qq.com/connect/oauth2/authorize?";
            $authorUrl .= "appid=".$appid;
            $authorUrl .= "&redirect_uri=".$redirect_uri;
            $authorUrl .= "&response_type=code";
            $authorUrl .= "&scope=snsapi_base";//不弹授权页面 静默获取openid
            $authorUrl .= "&state=".$queryString;
            $authorUrl .= "#wechat_redirect";
            // 记录授权地址
		    $this->wxlog($authorUrl,__FILE__,__LINE__,'授权地址');
            header($authorUrl);
            exit;
        }
        else
        {
            //读取到openid 则直接进入页面
            $page = $_GET["target"].".html";
            header("location: http://qiaodev.natapp4.cc/SJBWEB/Public/phpfile/common/".$page);
            exit;
        }
    }
    public function queryFormat(){
        // 只允许get参数
        $dataQuery = $_GET;
        // target->目标页面
        $target = $dataQuery["target"];
        // 记录入口参数
        $this->wxlog($_SERVER["QUERY_STRING"],__FILE__,__LINE__,'入口参数');
        if(!isset($target)){
            //缺少必要参数 没有目标页面
            header("location: http://qiaodev.natapp4.cc/SJBWEB/Public/phpfile/common/backerror.html?code=target");
            exit;
        }
        // 地址栏参数
        $queryString = urlencode($_SERVER["QUERY_STRING"]);
        return $queryString;
    }
    // $string： 明文 或 密文
    // $operation：DECODE表示解密,其它表示加密
    // $key： 密匙
    // $expiry：密文有效期
    public function authcode($string, $operation = 'DECODE', $cookiename='', $expiry = 0) {
         // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
         $ckey_length = 12;
         // 密匙
         $key = md5($this->RouterApi['wx_secret']);

         // 密匙a会参与加解密
         $keya = md5(substr($key, 0, 16));
         // 密匙b会用来做数据完整性验证
         $keyb = md5(substr($key, 16, 16));
         // 密匙c用于变化生成的密文
         $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
         // 参与运算的密匙
         $cryptkey = $keya.md5($keya.$keyc);
         $key_length = strlen($cryptkey);
         // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
         // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
         $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
         $string_length = strlen($string);
         $result = '';
         $box = range(0, 255);
         $rndkey = array();
         // 产生密匙簿
         for($i = 0; $i <= 255; $i++) {
                 $rndkey[$i] = ord($cryptkey[$i % $key_length]);
             }
             // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
         for($j = $i = 0; $i < 256; $i++) {
                 $j = ($j + $box[$i] + $rndkey[$i]) % 256;
                 $tmp = $box[$i];
                 $box[$i] = $box[$j];
                 $box[$j] = $tmp;
             }
         // 核心加解密部分
         for($a = $j = $i = 0; $i < $string_length; $i++) {
                 $a = ($a + 1) % 256;
                 $j = ($j + $box[$a]) % 256;
                 $tmp = $box[$a];
                 $box[$a] = $box[$j];
                 $box[$j] = $tmp;
                 // 从密匙簿得出密匙进行异或，再转成字符
                 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
             }
         if($operation == 'DECODE') {
                 // substr($result, 0, 10) == 0 验证数据有效性
                 // substr($result, 0, 10) - time() > 0 验证数据有效性
                 // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
                 // 验证数据有效性，请看未加密明文的格式
                if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
                    return substr($result, 26);
                }
                else {
                    return '';
                }
         } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            $strcode = $keyc.str_replace('=', '', base64_encode($result));
            if($cookiename!='')
            {
                setcookie("resultData",null,'/');
                setcookie("resultData",$strcode,time()+3600*24*30,'/');
            }
            return $strcode;
        }
    }
    //打印日志
    public function wxlog($arr,$file,$line,$flag = "array"){
		if(is_array($arr)){
			$log = $arr;
		}else{
			$log["value"] = $arr;
		}
		$content = "File => ".end(explode('\\',$file))." on line:".$line."\r\n";
		$content .= date("Y/m/d H:i:s")." ".$flag."(";

		foreach ($log as $key => $value) {
			if(is_array($value)){
				$content .= "\r\n    '".$key."' => '".urldecode(json_encode($value))."'";
			}else{
				$content .= "\r\n    '".$key."' => '".$value."'";
			}
		}
		$content .= "\r\n)\r\n\r\n";
        $log_filename = 'log/'.date("Ymd").".log";
        if(file_exists($log_filename)){
			file_put_contents($log_filename, $content ,FILE_APPEND);
        }else{
        	file_put_contents($log_filename, $content);
        }
	}
}
?>